20180913 畫出K線圖和KD值

這次代碼超長,也需要用前一節代碼,也需要用到很多新模組。

0.導入模組

  • tqdm: 跑進度條的模組
  • mpl_finance: 畫蠟燭圖 (上一節有解釋)
  • talib: 畫KD圖,這是在python一個技術分析模組 (pip3 install ta-lib),通常pip安裝會遇到問題,請到此網址https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib ,找到"正確"的版本,,到whl檔案所在目錄自行安裝 (pip3 install xxxxxxxxx.whl ) ,如果失敗通常是python的版本跟你想的不一樣。
  • matplotlib.gridspec: 要將多張圖化在一起使用的模組
  • matplotlib.ticker: 將x軸標籤化會使用
#導入模組
import pandas as pd
from datetime import datetime
import time 
from tqdm import tqdm
import numpy as np
import mpl_finance as mpf
import matplotlib.gridspec as gridspec
import matplotlib.ticker as ticker
import matplotlib.pyplot as plt

1.抓取個股日成交資訊

首先我們一樣要抓取個股的日成交的資訊,這次用input的方式,
因為上市和上櫃的html的網址位置不同,我們用try/except的方法把這部分補完。
先試抓證交所的資料(try),如果沒有就走櫃買的資料(except)

#帶出現在月份
date = datetime.now()
day = int(int(str(date)[8:10]))  
month = int(int(str(date)[5:7]))
if day<=4:  #如果月初(又剛好是假日)可能沒資料,我們把月份減一個月來收資料
    month = int(int(str(date)[5:7]))-1

#個股代碼  
stockno = input('請輸入股票代碼: ') 

#設定空df:table / 迴圈預設值m=1 / process bar(進度條 pbar)
table = pd.DataFrame()
m=1
pbar = tqdm(total = month) 

#上市走try,上櫃走except 
try:  
    pd.read_html('http://www.twse.com.tw/exchangeReport/STOCK_DAY?response=html&date=20180'+str(month-1)+'01&stockNo='+str(stockno))[0]
    while m<=month:   
        df = pd.read_html('http://www.twse.com.tw/exchangeReport/STOCK_DAY?response=html&date=20180'+str(m)+'01&stockNo='+str(stockno))[0]
        df.columns=['日期','成交股數','成交金額','開盤價','最高價','最低價','收盤價','漲跌價差','成交筆數']
        table = pd.concat([table,df],ignore_index=True)
        m += 1
        time.sleep(1) #讓每次抓取間隔1sec,跑太快會被證交所封鎖ip
        pbar.update(1) #update進度條
except:  
    while m<=month:
        df = pd.read_html('http://www.tpex.org.tw/web/stock/aftertrading/daily_trading_info/st43_print.php?l=zh-tw&d=107/'+str(m)+'&stkno='+str(stockno))[0]
        df.columns=['日期','成交股數','成交金額','開盤價','最高價','最低價','收盤價','漲跌價差','成交筆數']
        df = df.drop(df.index[-1:])
        table = pd.concat([table,df],ignore_index=True)
        m += 1
        time.sleep(1) #讓每次抓取間隔1sec,跑太快會被證交所封鎖ip
        pbar.update(1) #update進度條

pbar.close() #關閉進度條

#將df:table的日期轉成西元年 
table['日期'] = table.apply(lambda x: x['日期'].replace(x['日期'][0:3],str(int(x['日期'][0:3])+ 1911)), axis=1)
table['日期'] = pd.to_datetime(table['日期'])

以2330為例,table的輸出會長這樣:

2.將資料轉換成所需要的格式

蠟燭圖只能吃array的格式,我們要將dataframe轉換成array,
除此之外為了將某些日期資料空白(休市)去掉,
我需要將時間資料標籤化成非時間格式(ex:1,2,3....),待做圖時才將標籤"名稱"轉成時間。

#建立一個新的df:data只取出talib需要的資料取出
data = table[['日期','開盤價','收盤價','最高價','最低價','成交股數']]
data.columns=['date','open','close','high','low','volume'] #重新命名欄位的名稱

#將資料取成array for做圖使用
date_tickers=data.date.values #取出時間標籤的array
#將原df的時間資料修改成 1,2,3.....的array (空白資料
quotes=np.array([tuple([i]+list(quote[1:])) for i,quote in enumerate(data.values)]) 

#定義function
#將標籤從1,2,3....轉回日期
def format_date(x,pos=None):
    if x<0 or x>len(date_tickers)-1:
        return ''
    return data['date'].iloc[int(x)].strftime('%Y-%m-%d')

#設定x軸:週期為20個資料/將1,2,3....轉回日期
def set_ticker(axes):
    axes.xaxis.set_major_locator(ticker.MultipleLocator(20)) #設置主座標的刻度週期
    axes.xaxis.set_major_formatter(ticker.FuncFormatter(format_date)) #設置主座標的標籤格式

3.做圖

我打算將蠟燭圖、成交量、KD值,繪製在一張圖表 (將使用到matplotlib.girdspec),
會先用gridspec給定一個框,在分別定義三張圖表的位置和內容 (以ax1,ax2,ax3表示)
其中會用到Talib的語法可以參考官方的document:http://mrjbq7.github.io/ta-lib/funcs.html

外框

fig = plt.figure(figsize=(15,8)) #先圖的外框一個大小 (單位為英寸)
gs = gridspec.GridSpec(4,1) #使用gridspec劃成幾等分的gird,其中(4,1)代表4列1欄

K線圖(蠟燭圖)+MA20

ax1= plt.subplot(gs[0:2,:]) #ax1的在grid裡的範圍,[0:2,:]表示 0~2列整欄
mpf.candlestick_ochl(ax1, quotes, width=0.7, colorup = 'r', colordown = 'g') #畫蠟燭圖(只能用array)
ax1.plot(talib.SMA(data['close'], timeperiod=20),alpha=0.6) #使用Talib來畫MA20
ax1.set_ylabel('Price') #設定Y座標名稱
ax1.set_xlabel('') #設定X座標名稱
ax1.set_title('stock no:'+stockno,size=10) #設定圖表名稱
set_ticker(ax1) #用前面定義的set_ticker這個function來做座標轉換

成交量

ax2= plt.subplot(gs[2,:],sharex=ax1) #ax2的範圍(sharex=ax1代表與ax1共用x軸)
plt.bar(quotes[:,0], data['volume'], width= 0.5) #畫成交量bar chart (x軸為quotes這個array的第1欄,
ax2.set_ylabel('Volume') #設定Y座標名稱
plt.setp(ax2.get_xticklabels(), visible=False) #隱藏ax2 x軸
set_ticker(ax2) #用前面定義的set_ticker這個function來做座標轉換

KD圖 (STOCHSLOW)


ax3= plt.subplot(gs[3,:],sharex=ax1) #ax3的範圍(共用x軸)
#抓出KD的值(K與D各為一組Series)
slowk, slowd = talib.STOCH(data['high'], data['low'], data['close'], fastk_period=5, slowk_period=3, slowk_matype=0, slowd_period=3, slowd_matype=0)
ax3.plot(quotes[:,0],slowk) #畫K值
ax3.plot(quotes[:,0],slowd) #畫D值
ax3.set_ylabel('KD') #設定Y座標名稱
ax3.set_xlabel('Date') #設定Y座標名稱
set_ticker(ax3)  #用前面定義的set_ticker這個function來做座標轉換
plt.setp(ax3.get_xticklabels(), visible=False) #隱藏ax3 x軸

plt.show() #show圖

results matching ""

    No results matching ""